﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Input;
using GalaSoft.MvvmLight.Messaging;
using MishraReader.AppServices;
using MishraReader.Services;
using MishraReader.ViewModels;

namespace MishraReader.Shell
{
    /// <summary>
    ///   Interaction logic for MishraReaderWindow.xaml
    /// </summary>
    public partial class MishraReaderWindow
    {

        /// <summary>
        ///   IsSynchronizing Read-Only Dependency Property
        /// </summary>
        private static readonly DependencyPropertyKey IsSynchronizingPropertyKey
            = DependencyProperty.RegisterReadOnly("IsSynchronizing", typeof(bool), typeof(MishraReaderWindow),
                                                  new FrameworkPropertyMetadata(false));

        /// <summary>
        ///   UnreadCount Read-Only Dependency Property
        /// </summary>
        private static readonly DependencyPropertyKey UnreadCountPropertyKey
            = DependencyProperty.RegisterReadOnly("UnreadCount", typeof(int), typeof(MishraReaderWindow),
                                                  new FrameworkPropertyMetadata(0));

        public static readonly DependencyProperty IsSynchronizingProperty = IsSynchronizingPropertyKey.DependencyProperty;

        public static readonly DependencyProperty UnreadCountProperty = UnreadCountPropertyKey.DependencyProperty;


        private readonly ILightWeakEventManager _eventManager;
        private readonly ObservableCollection<ShareServiceJobViewModel> _events;
        private readonly IGoogleReaderService _gService;

        private readonly PropertyObserver<IGoogleReaderService> _gServiceObserver;
        private readonly IMainViewModel _mainViewModel;

        private readonly IMessenger _messenger;
        private readonly IOptionsManager _optionsManager;
        private readonly IShareServiceManager _shareServiceManager;
        private readonly IWindowPositionTracker _tracker;

        public MishraReaderWindow()
        {

            _events = new ObservableCollection<ShareServiceJobViewModel>();

            InitializeComponent();

        }

        public MishraReaderWindow(
            IMainViewModel mainViewModel,
            Func<Window, IWindowPositionTracker> windowTrackerFactory,
            IShareServiceManager shareServiceManager,
            IOptionsManager optionsManager,
            ILightWeakEventManager eventManager,
            IMessenger messenger,
            IGoogleReaderService gService)
            : this()
        {
            _mainViewModel = mainViewModel;
            _shareServiceManager = shareServiceManager;
            _optionsManager = optionsManager;
            _eventManager = eventManager;
            _messenger = messenger;
            _gService = gService;

            _tracker = windowTrackerFactory(this);
            _tracker.Start();

            _optionsManager.UpdateAccentColor();

            _shareServiceManager.JobStateChanged += CurrentJobStateChanged;

            _gServiceObserver = PropertyObserver.Create(_gService);

            // Relay property change notifications from the service to the proxied property
            _gServiceObserver.RegisterHandler(g => g.UnreadCount, o => SetUnreadCount(o.UnreadCount));
            _gServiceObserver.RegisterHandler(g => g.IsSync, g => SetIsSynchronizing(g.IsSync));
        }

        public IEnumerable<ShareServiceJobViewModel> Events
        {
            get { return _events; }
        }

        /// <summary>
        ///   Gets the IsSynchronizing property. This dependency property indicates ....
        /// </summary>
        public bool IsSynchronizing
        {
            get { return (bool)GetValue(IsSynchronizingProperty); }
        }

        /// <summary>
        ///   Gets the UnreadCount property. This dependency property indicates ....
        /// </summary>
        public int UnreadCount
        {
            get { return (int)GetValue(UnreadCountProperty); }
        }

        protected override void OnReady()
        {
            // Bug if dialog is displayed too quickly a the chrome border appears
            Dispatcher.BeginInvoke(new Action(() => contentPart.Content = _mainViewModel));
            base.OnReady();
        }

        /// <summary>
        ///   Provides a secure method for setting the IsSynchronizing property. This dependency property indicates ....
        /// </summary>
        /// <param name="value"> The new value for the property. </param>
        protected void SetIsSynchronizing(bool value)
        {
            SetValue(IsSynchronizingPropertyKey, value);
        }

        /// <summary>
        ///   Provides a secure method for setting the UnreadCount property. This dependency property indicates ....
        /// </summary>
        /// <param name="value"> The new value for the property. </param>
        protected void SetUnreadCount(int value)
        {
            SetValue(UnreadCountPropertyKey, value);
        }


        private void CurrentJobStateChanged(object sender, ShareServiceJobStateChangedEventArgs e)
        {
            Dispatcher.BeginInvoke(
                new Action(
                    () =>
                        {
                            switch (e.State)
                            {
                                case ShareServiceJobState.Working:
                                    {
                                        var vm = new ShareServiceJobViewModel
                                                     {
                                                         Job = e.Job
                                                     };
                                        vm.Message = String.Format(Strings.SharingOn,
                                                                   vm.Job.ServiceAccount.
                                                                       ServicePackage.ServiceName);
                                        _events.Insert(0, vm);
                                    }

                                    break;

                                case ShareServiceJobState.Completed:
                                    {
                                        var vm =
                                            _events.FirstOrDefault(job => job.Job == e.Job);
                                        if (vm != null)
                                            _events.Remove(vm);
                                    }
                                    break;

                                case ShareServiceJobState.Failure:
                                    {
                                        var vm =
                                            _events.FirstOrDefault(job => job.Job == e.Job);
                                        if (vm != null)
                                            _events.Remove(vm);
                                    }
                                    break;
                            }
                        }));
        }


        private void Window_Closing(object sender, CancelEventArgs e)
        {
            _eventManager.Send(ApplicationMessages.ApplicationClosing);
            _messenger.Unregister(this);
        }

        private void Window_StateChanged(object sender, EventArgs e)
        {
            if (WindowState != WindowState.Minimized)
            {
                ShowInTaskbar = true;
                notificationIcon.UpdateVisibility(false);
            }
            else if (_optionsManager.UseNotificationIcon)
            {
                notificationIcon.UpdateVisibility(true);

                if (WindowState == WindowState.Minimized && _optionsManager.ShowInTaskbar)
                {
                    ShowInTaskbar = true;
                }
                else if (WindowState == WindowState.Minimized && !_optionsManager.ShowInTaskbar)
                {
                    ShowInTaskbar = false;
                    Hide();
                }
            }
        }

        private void notificationIcon_MouseClick(object sender, MouseButtonEventArgs e)
        {
            Show();

            WindowState = WindowState.Normal;

            Activate();
        }
    }
}